import { _decorator, Component, Node, isValid } from 'cc';
import { EDITOR } from 'cc/env';

const { ccclass, property } = _decorator;
/** 是否启用全局单点 */
let isEnabledGlobalTouch = true;


@ccclass('MonoBehavior')
export class MonoBehavior extends Component {
    allEvents = {};
    protected _assetCaches = [];

    onInstantiateToInit() {
        this._assetCaches = [];
    }

    // =======================================
    // Component 生命周期
    // =======================================
    onEnable() {
        let events;
        for (const key in this.allEvents) {
            events = this.allEvents[key];
            events && events.map(eventInfo => {
                if (eventInfo.isRegisted) { return; }
                gg.systemEvent.on(eventInfo.eventName, eventInfo.callback, eventInfo.target);
                eventInfo.isRegisted = !0;
            });
        }

        this['onEnabled'] && this['onEnabled']();
        this['onEnterAnimation'] && this['onEnterAnimation']();
    }

    onDisable() {
        let events;
        for (const key in this.allEvents) {
            events = this.allEvents[key];
            events && events.map(eventInfo => {
                if (!eventInfo.isRegisted || eventInfo.isResident) { return; }
                gg.systemEvent.off(eventInfo.eventName, eventInfo.callback, eventInfo.target);
                eventInfo.isRegisted = !1;
            });
        }

        this['onExitAnimation'] && this['onExitAnimation']();
        this['onDisabled'] && this['onDisabled']();
    }

    onLoad() {
        // MonoBehavior.compareId();
        this.onBindEvents && this.onBindEvents();
        this['onLoadConfig'] && this['onLoadConfig']();
        this['onLoaded'] && this['onLoaded']();
    }

    start() {
        this['onStart'] && this['onStart']();
    }

    update(dt) {
        if (this['onUpdate']) {
            this.update = this['onUpdate'];
            this['onUpdate'](dt);
        } else {
            this.update = (dt) => { };
        }
    }

    lateUpdate(dt) {
        if (this['onLateUpdate']) {
            this.lateUpdate = this['onLateUpdate'];
            this['onLateUpdate'](dt);
        } else {
            this.lateUpdate = (dt) => { };
        }
    }

    onDestroy() {
        if (!0) {
            // 注销驻留的函数
            let events;
            for (const key in this.allEvents) {
                events = this.allEvents[key];
                events && events.map(eventInfo => {
                    if (!eventInfo.isRegisted) { return; }
                    gg.systemEvent.off(eventInfo.eventName, eventInfo.callback, eventInfo.target);
                    eventInfo.isRegisted = !1;
                });
            }
        }

        this['onRemoveEvents'] && this['onRemoveEvents']();
        this['onDestroyed'] && this['onDestroyed']();

        // 释放资源
        for (let i = 0; i < this._assetCaches.length; i++) {
            if (gg.isValid(this._assetCaches[i], true) && this._assetCaches[i].decRef) {
                this._assetCaches[i].decRef();
            }
        }
        this._assetCaches = [];
    }


    // =======================================
    // 模板方法
    // =======================================
    onBindEvents() {
        // toucu事件
        if (this['onTouchStart'] || this['onTouchEnded']) {
            this.node.on(Node.EventType.TOUCH_START, this._onTouchStart, this);
            this.node.on(Node.EventType.TOUCH_END, this._onTouchEnded, this);
            this.node.on(Node.EventType.TOUCH_CANCEL, this._onTouchCancelled, this);
        }
        if (this['onTouchMoved']) {
            this.node.on(Node.EventType.TOUCH_MOVE, this._onTouchMoved, this);
        }
        this['onAddEvents'] && this['onAddEvents']();
    }
    /** 注册事件 */
    // onAddEvents() {

    // }

    /** 取消事件注册 */
    // onRemoveEvents() {

    // }

    /** 初始化配置 */
    // onLoadConfig() {

    // }

    /** onLoad结束的回调 */
    // onLoaded() {

    // }

    /** 在组件第一次update前调用，做一些初始化逻辑 */
    // onStart() {

    // }

    /**
     * 场景动画更新前回调
     * @param dt 游戏帧时长
     */
    // onUpdate(dt) {

    // }

    /** 场景动画更新后回调 */
    // onLateUpdate(dt) {

    // }

    /** 销毁组件 */
    // onDestroyed() {

    // }


    // =======================================
    // 功能方法
    // =======================================

    _onTouchStart(event) {
        if (isEnabledGlobalTouch && this._getTouchId(event) > 0) { return; }
        this['onTouchStart'] && this['onTouchStart'](event);
    }
    _onTouchMoved(event) {
        if (isEnabledGlobalTouch && this._getTouchId(event) > 0) { return; }
        this['onTouchMoved'] && this['onTouchMoved'](event);
    }
    _onTouchEnded(event) {
        if (isEnabledGlobalTouch && this._getTouchId(event) > 0) { return; }
        this['onTouchEnded'] && this['onTouchEnded'](event);
    }
    _onTouchCancelled(event) {
        if (isEnabledGlobalTouch && this._getTouchId(event) > 0) { return; }

        if (this['onTouchCancelled']) {
            this['onTouchCancelled'](event);
        } else if (this['onTouchEnded']) {
            this['onTouchEnded'](event);
        }
    }

    _getTouchId(event) {
        const touchs = event.getTouches();
        return touchs.indexOf(event.touch);
    }



    // =======================================
    // 功能方法
    // =======================================

    /** 缓存资源 */
    protected cacheAsset(asset) {
        if (!gg.isValid(asset)) return asset;
        if (!gg.isValid(this.node)) return asset.decRef();
        asset.addRef();
        this._assetCaches?.push(asset);
        return asset;
    }

    /** 注册事件 */
    registerEvent(eventName, callback, target, isResident?) {
        if (EDITOR) { return; }
        isResident = !!isResident;
        this.allEvents[eventName] = this.allEvents[eventName] || [];
        let isRegisted = !1;
        // 如果节点已启用，直接注册事件
        if (this.enabled) {
            gg.systemEvent.on(eventName, callback, target);
            isRegisted = !0;
        }
        this.allEvents[eventName].push({ eventName, callback, target, isResident, isRegisted });
    }

    /** 触发事件 */
    emitEvent(eventName, data) {
        return gg.systemEvent.emit(eventName, data);
    }

    /**
     * 设置是否启用单点
     * @param {*} isEnabled 
     */
    setEnableTouchOneByOne(isEnabled) {
        isEnabledGlobalTouch = !!isEnabled;
    }

    getNodePath(node, pathStr) {
        if (!node) { node = this.node; }
        if (!node) { return pathStr; }

        const parent = node.parent;
        if (!parent) { return pathStr; }

        const name = node.name;
        if (!name) { return pathStr; }

        return this.getNodePath(parent, pathStr ? name + '/' + pathStr : name);
    }

    getNodesTree(node) {
        if (!node) node = this.node;
        for (let index = 0; index < node.children.length; index++) {
            const element = node.children[index];
            node[element.name] = element;
            this.getNodesTree(element);
        }
        return node;
    }
}
